package com.allen.app.common.config.aspect;

import cn.hutool.core.util.RandomUtil;
import com.allen.app.common.utils.CheckObjectUtils;
import com.allen.app.common.utils.Jackson;
import com.allen.app.common.utils.ServletContextUtil;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ObjectUtils;

/**
*
* Description: 切面工具类
*
* @author Limiaojun
* @date 2020/1/9 12:22
**/
@Slf4j
@UtilityClass
public class AcpectCommonUtils {

    private ExpressionParser parser = new SpelExpressionParser();
    private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();

    public String parseKey(String key, Method method, Object[] args) {
        EvaluationContext context = new StandardEvaluationContext();
        String[] params = discoverer.getParameterNames(method);
        if (!ObjectUtils.isEmpty(params)) {
            for (int i = 0; i < params.length; i++) {
                context.setVariable(params[i], args[i]);
            }
        }
        try {
            return parser.parseExpression(key).getValue(context, String.class);
        } catch (SpelEvaluationException e) {
            return key;
        }
    }

    /**
     * 获取参数名称数组.
     *
     * @param proceedingJoinPoint proceedingJoinPoint
     * @return java.lang.String[]
     * @author Limiaojun
     * @date 2019/8/2 17:40
     */
    public static String[] getParameterNames(ProceedingJoinPoint proceedingJoinPoint) {
        MethodSignature methodSignature = getMethodSignature(proceedingJoinPoint);
        return methodSignature.getParameterNames();
    }

    /**
     * 获取参数值数组对象.
     *
     * @param proceedingJoinPoint proceedingJoinPoint
     * @return java.lang.Object[]
     * @author Limiaojun
     * @date 2019/8/2 17:40
     */
    public static Object[] getArgs(ProceedingJoinPoint proceedingJoinPoint) {
        return proceedingJoinPoint.getArgs();
    }

    /**
     * 获取类名称.
     *
     * @param proceedingJoinPoint proceedingJoinPoint
     * @return java.lang.String
     * @author Limiaojun
     * @date 2019/8/2 17:58
     */
    public static String getClassName(ProceedingJoinPoint proceedingJoinPoint) {
        return proceedingJoinPoint.getTarget().getClass().getSimpleName();
    }

    /**
     * 获取完整的类名称[包名.类名].
     *
     * @param proceedingJoinPoint proceedingJoinPoint
     * @return java.lang.String
     * @author Limiaojun
     * @date 2019/8/2 17:58
     */
    public static String getCompleteClassName(ProceedingJoinPoint proceedingJoinPoint) {
        return proceedingJoinPoint.getTarget().getClass().getName();
    }

    /**
     * 获取方法名称.
     *
     * @param proceedingJoinPoint proceedingJoinPoint
     * @return java.lang.String
     * @author Limiaojun
     * @date 2019/8/2 17:58
     */
    public static String getMethodName(ProceedingJoinPoint proceedingJoinPoint) {
        MethodSignature methodSignature = getMethodSignature(proceedingJoinPoint);
        return methodSignature.getMethod().getName();
    }

    /**
     * This is a getMethodSignature.
     *
     * @param proceedingJoinPoint proceedingJoinPoint
     * @return org.aspectj.lang.reflect.MethodSignature
     * @author Limiaojun
     * @date 2019/8/2 17:58
     */
    private static MethodSignature getMethodSignature(ProceedingJoinPoint proceedingJoinPoint) {
        return (MethodSignature) proceedingJoinPoint.getSignature();
    }

    /**
     * 获取注解类.
     *
     * @param proceedingJoinPoint proceedingJoinPoint
     * @param annotationClass annotationClass
     * @return T
     * @author Limiaojun
     * @date 2019/9/19 14:52
     */
    public static  <T extends Annotation> T getAnnotationClass(ProceedingJoinPoint proceedingJoinPoint, Class<T> annotationClass) {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        return methodSignature.getMethod().getAnnotation(annotationClass);
    }

}
